package com.hm.cms.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;

import com.hm.cms.auto.su.BaseDomain;
import com.hm.cms.auto.su.R;
import com.hm.cms.domain.ArticleContentDomain;
import com.hm.cms.domain.ArticleDomain;
import com.hm.cms.domain.QArticleContentDomain;
import com.hm.cms.domain.QArticleDomain;
import com.hm.cms.domain.QTermTayRelationshipsDomain;
import com.hm.cms.domain.TermTayRelationshipsDomain;
import com.hm.cms.repository.ArticleContentRepository;
import com.hm.cms.repository.ArticleRepository;
import com.hm.cms.repository.TermTaxonomyRepository;
import com.hm.cms.repository.TermTayRelationshipsRepository;
import com.hm.cms.repository.TermsRepository;
import com.hm.cms.su.BeanUtil;
import com.hm.cms.vo.HcmsArticleVo;
import com.hm.cms.vo.HcmsArticleVo.ArticleNavgVo;
import com.hm.common.def.DataStatusDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.redis.jedis.JedisFactory;
import com.hm.common.redis.jedis.su.JedisHandler;
import com.hm.common.redis.jedis.su.JedisHandlerSupport;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageInfoParam;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.DateUtil;
import com.hm.common.util.RandomUtil;
import com.querydsl.core.types.dsl.BooleanExpression;

/**
 * @author shishun.wang
 * @date 下午2:45:20 2017年10月13日
 * @version 1.0
 * @describe
 */
@Service
public class ArticleServiceImpl implements ArticleService {

	@Autowired
	private TermsRepository termsRepository;

	@Autowired
	private JedisHandlerSupport jedisHandler;

	@Autowired
	private ArticleRepository articleRepository;

	@Autowired
	private TermTaxonomyRepository termTaxonomyRepository;

	@Autowired
	private ArticleContentRepository articleContentRepository;

	@Autowired
	private TermTayRelationshipsRepository termTayRelationshipsRepository;

	@Override
	public void addArticle(HcmsArticleVo articleVo, String operationUserId) {
		if (CommonUtil.isAnyEmpty(articleVo.getTitle(), articleVo.getArticleExcerpt(), articleVo.getArticleContent(),
				articleVo.getKeywords())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		if (CommonUtil.isAllEmpty(articleVo.getTermIds(), articleVo.getTermTayIds())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ArticleDomain articleDomain = new ArticleDomain();
		{
			BeanUtil.copyProperties(articleVo, articleDomain);
			BaseDomain.initBaseInfo(articleDomain);
			articleDomain.setReleaseTime(new Date(articleVo.getReleaseTime()));
			articleDomain.setCreateUser(operationUserId);
		}
		ArticleDomain article = articleRepository.save(articleDomain);

		// 页面内容保存
		ArticleContentDomain articleContentDomain = new ArticleContentDomain();
		{
			BeanUtil.copyProperties(articleVo, articleContentDomain);
			BaseDomain.initBaseInfo(articleContentDomain);
			articleContentDomain.setCreateUser(operationUserId);
			articleContentDomain.setArticleId(article.getId());
		}
		articleContentRepository.save(articleContentDomain);

		// 随机阅读量设置
		// ViewQuantityDomain quantityDomain = new ViewQuantityDomain();
		// {
		// quantityDomain.setArticleId(article.getId());
		// quantityDomain.setTotal(RandomUtil.randomNumber(10, 50));
		// BaseDomain.initBaseInfo(quantityDomain);
		// }
		// ViewQuantityDomain viewQuantityDomain =
		// viewQuantityRepository.save(quantityDomain);

		// 设置文章标签及分类关系
		TermTayRelationshipsDomain relationshipsDomain = new TermTayRelationshipsDomain();
		{
			BeanUtil.copyProperties(articleVo, relationshipsDomain);
			BaseDomain.initBaseInfo(relationshipsDomain);
			relationshipsDomain.setViewQuantity(RandomUtil.randomNumber(3, 10));
			relationshipsDomain.setCommentQuantity(RandomUtil.randomNumber(3, 10));
			relationshipsDomain.setArticleId(article.getId());
		}
		termTayRelationshipsRepository.save(relationshipsDomain);
	}

	@Override
	public PageInfo<HcmsArticleVo> queryArticle(PageInfoParam pageParam, String termTayId, String termId) {
		QTermTayRelationshipsDomain qTermTayRelationshipsDomain = QTermTayRelationshipsDomain.termTayRelationshipsDomain;

		Pageable pageable = new QPageRequest(pageParam.getPage(), pageParam.getSize(),
				qTermTayRelationshipsDomain.createTime.desc());

		BooleanExpression predicate = qTermTayRelationshipsDomain.status.eq(DataStatusDef.ENABLE);
		if (CommonUtil.isNotEmpty(termTayId)) {
			predicate = predicate.and(qTermTayRelationshipsDomain.termTayIds.contains(termTayId));
		}
		if (CommonUtil.isNotEmpty(termId)) {
			predicate = predicate.and(qTermTayRelationshipsDomain.termIds.contains(termId));
		}

		Page<TermTayRelationshipsDomain> page = termTayRelationshipsRepository.findAll(predicate, pageable);

		List<HcmsArticleVo> vos = new ArrayList<HcmsArticleVo>();
		page.getContent().forEach(relation -> {
			if (CommonUtil.isAnyEmpty(relation.getTermIds(), relation.getTermTayIds())) {
				return;
			}

			ArticleDomain articleDomain = articleRepository
					.findOne(QArticleDomain.articleDomain.id.eq(relation.getArticleId()));
			if (CommonUtil.isEmpty(articleDomain)) {
				return;
			}
			HcmsArticleVo vo = new HcmsArticleVo();
			BeanUtil.copyProperties(articleDomain, vo);

			vo.setViewQuantity(relation.getViewQuantity()
					+ (CommonUtil.isEmpty(relation.getRealViewQuantity()) ? 0 : relation.getRealViewQuantity()));
			vo.setCommentQuantity(relation.getCommentQuantity()
					+ (CommonUtil.isEmpty(relation.getRealCommentQuantity()) ? 0 : relation.getRealCommentQuantity()));
			vo.setArticleId(articleDomain.getId());
			vo.setReleaseTime(DateUtil.data2long(articleDomain.getReleaseTime()));

			if (CommonUtil.isNotEmpty(articleDomain.getStaticizeUri())) {
				 vos.add(vo);
				return;
			}

			StringBuffer uri = new StringBuffer("article/");

			// 设置标签链接uri
			Optional.ofNullable(termTaxonomyRepository.findOne(relation.getTermTayIds().get(0)))
					.ifPresent(taxonomyDomain -> {
						uri.append(taxonomyDomain.getTermTayCode() + "/");
						// vo.setStaticizeUri("o_term_taxonomy/" +
						// taxonomyDomain.getTermTayCode() + "/" +
						// articleDomain.getId());
					});

			// 设置分类链接uri
			Optional.ofNullable(termsRepository.findOne(relation.getTermIds().get(0))).ifPresent(termsDomain -> {
				uri.append(termsDomain.getTermCode() + "/");
				// vo.setStaticizeUri("o_term/" + termsDomain.getTermCode() +
				// "/" + articleDomain.getId());
			});

			vo.setStaticizeUri(uri.toString() + articleDomain.getId());
			vos.add(vo);
		});

		return new PageInfo<HcmsArticleVo>(vos, page.getTotalPages(), page.getTotalElements());
	}

	@Override
	public HcmsArticleVo getArticleInfo(String articleId) {
		if (CommonUtil.isEmpty(articleId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		ArticleDomain articleDomain = articleRepository.findOne(articleId);
		if (CommonUtil.isEmpty(articleDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}
		HcmsArticleVo vo = new HcmsArticleVo();
		BeanUtil.copyProperties(articleDomain, vo);
		vo.setReleaseTime(DateUtil.data2long(articleDomain.getReleaseTime()));

		TermTayRelationshipsDomain relationshipsDomain = termTayRelationshipsRepository
				.findOne(QTermTayRelationshipsDomain.termTayRelationshipsDomain.articleId.eq(articleDomain.getId()));
		if (CommonUtil.isEmpty(relationshipsDomain)) {
			return vo;
		}
		vo.setViewQuantity(relationshipsDomain.getViewQuantity()
				+ (CommonUtil.isEmpty(relationshipsDomain.getRealViewQuantity()) ? 0
						: relationshipsDomain.getRealViewQuantity()));
		vo.setCommentQuantity(relationshipsDomain.getCommentQuantity()
				+ (CommonUtil.isEmpty(relationshipsDomain.getRealCommentQuantity()) ? 0
						: relationshipsDomain.getRealCommentQuantity()));

		ArticleContentDomain articleContentDomain = articleContentRepository
				.findOne(QArticleContentDomain.articleContentDomain.articleId.eq(articleDomain.getId()));
		if (CommonUtil.isEmpty(articleContentDomain)) {
			return vo;
		}
		vo.setArticleContent(articleContentDomain.getArticleContent());

		{// 下一页
			QArticleDomain qArticleDomain = QArticleDomain.articleDomain;
			Pageable pageable = new QPageRequest(0, 1, qArticleDomain.articleOrder.asc());
			articleRepository.findAll(qArticleDomain.articleOrder.gt(articleDomain.getArticleOrder()), pageable)
					.getContent().forEach(article -> {
						ArticleNavgVo nextPage = new ArticleNavgVo();
						{
							nextPage.setArticleId(article.getId());
							nextPage.setNavName(article.getTitle());
							nextPage.setNavUri(CommonUtil.isEmpty(article.getStaticizeUri())
									? generationArticleUri(article.getId())
									: article.getStaticizeUri());
						}
						vo.setNextPage(nextPage);
					});
		}

		{// 上一页
			QArticleDomain qArticleDomain = QArticleDomain.articleDomain;
			Pageable pageable = new QPageRequest(0, 1, qArticleDomain.articleOrder.desc());
			articleRepository.findAll(qArticleDomain.articleOrder.lt(articleDomain.getArticleOrder()), pageable)
					.getContent().forEach(article -> {
						ArticleNavgVo nextPage = new ArticleNavgVo();
						{
							nextPage.setArticleId(article.getId());
							nextPage.setNavName(article.getTitle());
							nextPage.setNavUri(CommonUtil.isEmpty(article.getStaticizeUri())
									? generationArticleUri(article.getId())
									: article.getStaticizeUri());
						}
						vo.setLastPage(nextPage);
					});
		}

		return vo;
	}

	private String generationArticleUri(String articleId) {
		if (CommonUtil.isEmpty(articleId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}
		TermTayRelationshipsDomain relationshipsDomain = termTayRelationshipsRepository
				.findOne(QTermTayRelationshipsDomain.termTayRelationshipsDomain.articleId.eq(articleId));
		if (CommonUtil.isEmpty(relationshipsDomain)) {
			return null;
		}

		if (CommonUtil.isAnyEmpty(relationshipsDomain.getTermTayIds(), relationshipsDomain.getTermIds())) {
			return null;
		}

		StringBuffer uri = new StringBuffer("article/");
		// 设置标签链接uri
		Optional.ofNullable(termTaxonomyRepository.findOne(relationshipsDomain.getTermTayIds().get(0)))
				.ifPresent(taxonomyDomain -> {
					uri.append(taxonomyDomain.getTermTayCode() + "/");
				});

		// 设置分类链接uri
		Optional.ofNullable(termsRepository.findOne(relationshipsDomain.getTermIds().get(0))).ifPresent(termsDomain -> {
			uri.append(termsDomain.getTermCode() + "/");
		});

		return uri.append(articleId).toString();
	}

	@Override
	public long getArtilcleMaxOrder() {
		Object object = jedisHandler.executeCommand(new JedisHandler() {

			@Override
			public Object handler(JedisFactory jedis) {
				String value = jedis.get(R.RedisKey.ARTICLE_ORDER_COUNT);
				if (CommonUtil.isEmpty(value)) {
					jedis.getJedis().incrBy(R.RedisKey.ARTICLE_ORDER_COUNT, articleRepository.count() + 1);
				}
				return jedis.incr(R.RedisKey.ARTICLE_ORDER_COUNT);
			}
		});

		return (long) object;
	}

	@Override
	public boolean checkArticleSourceUri(String sourceUri) {
		// return
		// CommonUtil.isNotEmpty(articleRepository.findAll(QArticleDomain.articleDomain.sourceUri.eq(sourceUri.trim())));
		return articleRepository.exists(QArticleDomain.articleDomain.sourceUri.eq(sourceUri.trim()));
	}

	@Override
	public List<HcmsArticleVo> recommendArticle(String termId) {
		QTermTayRelationshipsDomain qTermTayRelationshipsDomain = QTermTayRelationshipsDomain.termTayRelationshipsDomain;

		Pageable pageable = new QPageRequest(1, RandomUtil.randomNumber(1, 3),
				qTermTayRelationshipsDomain.createTime.desc());

		BooleanExpression predicate = qTermTayRelationshipsDomain.status.eq(DataStatusDef.ENABLE)
				.and(qTermTayRelationshipsDomain.termIds.contains(termId));

		List<HcmsArticleVo> vos = new ArrayList<HcmsArticleVo>();
		termTayRelationshipsRepository.findAll(predicate, pageable).getContent().parallelStream().forEach(item -> {
			ArticleDomain articleDomain = articleRepository
					.findOne(QArticleDomain.articleDomain.id.eq(item.getArticleId()));
			if (CommonUtil.isEmpty(articleDomain)) {
				return;
			}

			HcmsArticleVo vo = new HcmsArticleVo();
			BeanUtil.copyProperties(articleDomain, vo);
			vo.setStaticizeUri(
					CommonUtil.isEmpty(articleDomain.getStaticizeUri()) ? generationArticleUri(articleDomain.getId())
							: articleDomain.getStaticizeUri());
			vos.add(vo);
		});

		return vos;
	}
}
